package view.graph {	
	import controller.ControllerManager;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import fl.transitions.Tween;
	import fl.transitions.easing.*;
	import flash.utils.getQualifiedClassName;
	import model.ModelManager;
	import model.Post;
	import model.PostRoot;
	import view.graph.states.GraphExpansionType;
	import view.graph.states.GraphState;
	import view.GraphicPost;
	import view.GraphicPostRoot;
	/**
	 * ...
	 * @author Anthony
	 */	
	public class GraphManager
	{
		//------------------------------- statics ------------------------------\\
		private static const GRAPHICPOSTPADDING : int = 25;
		
		private static var _self : GraphManager = new GraphManager();		
		
		//------------------------------ variables -----------------------------\\
		private var _graphic 			: Sprite;
		private var _graphicPostRoot	: GraphicPostRoot;
		private var _graphGraphicPosts	: Object /*GraphicPost*/;
		
		//------------------------------ accessors -----------------------------\\
		public static function get self() 		: GraphManager 				{ return _self; }
		public function get graphic() 			: Sprite 					{ return _graphic; }
		public function get graphGraphicPosts()	: Object /*GraphicPost*/ 	{ return _graphGraphicPosts; }
		
		//-------------------------- public functions --------------------------\\
		public function GraphManager()
		{			
			if (_self)
				throw new Error("GraphManager can only be accessed through GraphManager.self");
			else
			{
				_graphic 			= new Sprite();
				_graphicPostRoot 	= GraphicPostRoot.self;
				_graphGraphicPosts 	= new Object();
			}
		}
		
		public function init() : void
		{			
			// Construct graphics from datas
			for (var currentKey : * in ModelManager.self.keys)
			{
				var currentPost : Post = ModelManager.self.getDataFromKey(ModelManager.self.keys[currentKey]);
				var currentGraphic : GraphicPost = (getQualifiedClassName(currentPost) == getQualifiedClassName(PostRoot.self))
														? GraphicPostRoot.self
														: new GraphicPost(currentPost);
				currentGraphic.init();
				_graphGraphicPosts[currentPost.key] = currentGraphic;
				_graphic.addChild(currentGraphic.graphic);
			}
			
			// Construct graph structure and update graphics positions
			constructGraphicPostsGraph(_graphicPostRoot);
			updateGraphicPostsPositions();
		}
		
		public function onGraphStateChange(changedState : GraphState) : void
		{
			if (changedState.changeGraphicPostsPositions)
				updateGraphicPostsPositions();
			if (changedState.changeGraphicPostsVisibility)
				updateGraphicPostsVisibility();
		}
		
		//public function translateGraphManager(
		
		public function goToNextBrother(target : GraphicPost) : void
		{
			var targetIndexInBrotherArray : Number = target.graphicAnswerOf.graphicAnswers.indexOf(target);
			if (targetIndexInBrotherArray < (target.graphicAnswerOf.graphicAnswers.length - 1))
			{
				var nextBrother : GraphicPost = target.graphicAnswerOf.graphicAnswers[targetIndexInBrotherArray + 1];
				var nextGraphXPosition : Number = _graphic.x - (nextBrother.graphic.x - target.graphic.x);
				new Tween(_graphic, "x", Strong.easeOut, _graphic.x, nextGraphXPosition, 1, true);
				//_graphic.x = nextGraphXPosition;
			}		
		}
		
		public function goToPreviousBrother(target : GraphicPost) : void
		{
			var targetIndexInBrotherArray : Number = target.graphicAnswerOf.graphicAnswers.indexOf(target);
			if (targetIndexInBrotherArray > 0)
			{
				var previousBrother : GraphicPost = target.graphicAnswerOf.graphicAnswers[targetIndexInBrotherArray - 1];
				var nextGraphXPosition : Number = _graphic.x - (previousBrother.graphic.x - target.graphic.x);
				new Tween(_graphic, "x", Strong.easeOut, _graphic.x, nextGraphXPosition, 1, true);
				//_graphic.x = nextGraphXPosition;
			}
		}
		
		//------------------------- private functions --------------------------\\			
		// Recursive - Save graph links beetween GraphicPost
		private function constructGraphicPostsGraph(currentGraphicPost : GraphicPost) : void
		{
			if (currentGraphicPost.data.answers.length > 0)
			{
				var graphSonsLengthSum : int = 0;
				for (var answerIndex : * in currentGraphicPost.data.answers)
				{
					var currentAnswer : Post = currentGraphicPost.data.answers[answerIndex];
					var currentGraphicAnswer : GraphicPost = _graphGraphicPosts[currentAnswer.key];
					currentGraphicPost.addAnswer(currentGraphicAnswer);
					
					constructGraphicPostsGraph(currentGraphicAnswer);
					graphSonsLengthSum += currentGraphicAnswer.graphSonsLength + 1;
				}
				currentGraphicPost.graphSonsLength = graphSonsLengthSum - 1;
			}
			else
			{
				currentGraphicPost.graphSonsLength = 0;
			}
		}
		
		private function updateGraphicPostsVisibility() : void
		{
			if (GraphStates.self.graphExpansionType == GraphExpansionType.CONDENSED)
			{
				// Hide all GraphicPosts
				_graphicPostRoot.changeAnswersVisibility(false);
				// Show only first answers
				_graphicPostRoot.changeAnswersVisibility(true, 1);
			}
			else if (GraphStates.self.graphExpansionType == GraphExpansionType.EXTENDED)
			{	
				// Show All GraphicPosts
				_graphicPostRoot.changeAnswersVisibility(true);
			}
		}
		
		private function updateGraphicPostsPositions() : void
		{
			var newPositions : Object /*Point*/ = getGraphicPostsPositions(_graphicPostRoot, new Object());
			for (var graphicPostKey : String in _graphGraphicPosts)
			{
				new Tween(_graphGraphicPosts[graphicPostKey].graphic, "x", Strong.easeOut, _graphGraphicPosts[graphicPostKey].graphic.x, newPositions[graphicPostKey].x, 1, true);
				new Tween(_graphGraphicPosts[graphicPostKey].graphic, "y", Strong.easeOut, _graphGraphicPosts[graphicPostKey].graphic.y, newPositions[graphicPostKey].y, 1, true);
				//_graphGraphicPosts[graphicPostKey].graphic.x = newPositions[graphicPostKey].x;
				//_graphGraphicPosts[graphicPostKey].graphic.y = newPositions[graphicPostKey].y;				
			}
		}		
		
		// Recursive - Get all GraphicPost positions (x;y), based on brother's and father's position and GraphStates values
		private function getGraphicPostsPositions(graphicPostTarget : GraphicPost, currentResult : Object /*Point*/) : Object /*Point*/
		{
			var currentAnswerIndex 		: int;
			var currentAnswerPosition 	: Point = new Point(0, 0);			
			
			if (getQualifiedClassName(graphicPostTarget) == getQualifiedClassName(GraphicPostRoot.self))
			{
				currentAnswerPosition.x = 0;
				currentAnswerPosition.y = 0;
			}
			else
			{
				currentAnswerPosition.y = currentResult[graphicPostTarget.graphicAnswerOf.data.key].y + graphicPostTarget.graphicAnswerOf.graphic.height + GRAPHICPOSTPADDING;
				
				currentAnswerIndex = graphicPostTarget.graphicAnswerOf.graphicAnswers.indexOf(graphicPostTarget);
				if (currentAnswerIndex == 0)
				{				
					currentAnswerPosition.x = currentResult[graphicPostTarget.graphicAnswerOf.data.key].x;
				}
				else
				{
					var previousGraphicBrother : GraphicPost = graphicPostTarget.graphicAnswerOf.graphicAnswers[currentAnswerIndex - 1];
						
					if (GraphStates.self.graphExpansionType == GraphExpansionType.CONDENSED)
					{					
						currentAnswerPosition.x = currentResult[previousGraphicBrother.data.key].x + previousGraphicBrother.graphic.width + GRAPHICPOSTPADDING;
					}
					else if (GraphStates.self.graphExpansionType == GraphExpansionType.EXTENDED)
					{					
						currentAnswerPosition.x = currentResult[previousGraphicBrother.data.key].x + previousGraphicBrother.getAnswersWidthSum() + (previousGraphicBrother.graphSonsLength + 1) * GRAPHICPOSTPADDING ;
					}
				}
			}
			
			currentResult[graphicPostTarget.data.key] = currentAnswerPosition;
			for (var i : int = 0 ; i < graphicPostTarget.graphicAnswers.length ; i++)
			{
				currentResult = getGraphicPostsPositions(graphicPostTarget.graphicAnswers[i], currentResult);				
			}
			return currentResult;
		}
				
		
	}
}